package com.code.train.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import com.code.train.domain.DailyTrain;
import com.code.train.domain.DailyTrainTicket;
import com.code.train.domain.DailyTrainTicketExample;
import com.code.train.domain.TrainStation;
import com.code.train.enums.SeatTypeEnum;
import com.code.train.enums.TrainTypeEnum;
import com.code.train.mapper.DailyTrainTicketMapper;
import com.code.train.req.DailyTrainTicketQueryReq;
import com.code.train.req.DailyTrainTicketSaveReq;
import com.code.train.resp.DailyTrainTicketQueryResp;
import com.code.train.resp.PageResp;
import com.code.train.service.DailyTrainSeatService;
import com.code.train.service.DailyTrainTicketService;
import com.code.train.service.TrainStationService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DailyTrainTicketServiceImpl implements DailyTrainTicketService {

    @Autowired
    private DailyTrainTicketMapper dailyTrainTicketMapper;

    @Autowired
    private TrainStationService trainStationService;

    @Autowired
    private DailyTrainSeatService dailyTrainSeatService;

    @Override
    public void save(DailyTrainTicketSaveReq req) {
        DateTime now = DateTime.now();
        DailyTrainTicket dailyTrainTicket = BeanUtil.copyProperties(req, DailyTrainTicket.class);
        if (ObjectUtil.isNull(dailyTrainTicket.getId())) {
            dailyTrainTicket.setId(System.currentTimeMillis());
            dailyTrainTicket.setCreateTime(now);
            dailyTrainTicket.setUpdateTime(now);
            dailyTrainTicketMapper.insert(dailyTrainTicket);
        } else {
            dailyTrainTicket.setUpdateTime(now);
            dailyTrainTicketMapper.updateByPrimaryKey(dailyTrainTicket);
        }
    }

    @CachePut(value = "DailyTrainTicketServiceImpl.queryList")
    public PageResp<DailyTrainTicketQueryResp> queryList2(DailyTrainTicketQueryReq req) {
        return queryList(req);
    }

    @Cacheable(value = "DailyTrainTicketServiceImpl.queryList")
    @Override
    public PageResp<DailyTrainTicketQueryResp> queryList(DailyTrainTicketQueryReq req) {
        DailyTrainTicketExample dailyTrainTicketExample = new DailyTrainTicketExample();
        dailyTrainTicketExample.setOrderByClause("id desc");
        DailyTrainTicketExample.Criteria criteria = dailyTrainTicketExample.createCriteria();
        if (ObjectUtil.isNotNull(req.getDate())) {
            criteria.andDateEqualTo(req.getDate());
        }
        if (ObjectUtil.isNotEmpty(req.getTrainCode())) {
            criteria.andTrainCodeEqualTo(req.getTrainCode());
        }
        if (ObjectUtil.isNotEmpty(req.getStart())) {
            criteria.andStartEqualTo(req.getStart());
        }
        if (ObjectUtil.isNotEmpty(req.getEnd())) {
            criteria.andEndEqualTo(req.getEnd());
        }

        log.info("查询页码：{}", req.getPage());
        log.info("每页条数：{}", req.getSize());
        PageHelper.startPage(req.getPage(), req.getSize());
        List<DailyTrainTicket> dailyTrainTicketList = dailyTrainTicketMapper.selectByExample(dailyTrainTicketExample);

        PageInfo<DailyTrainTicket> pageInfo = new PageInfo<>(dailyTrainTicketList);
        log.info("总行数：{}", pageInfo.getTotal());
        log.info("总页数：{}", pageInfo.getPages());

        List<DailyTrainTicketQueryResp> list = dailyTrainTicketList.stream()
                .map(dailyTrainTicket -> {
                    DailyTrainTicketQueryResp resp = new DailyTrainTicketQueryResp();
                    BeanUtils.copyProperties(dailyTrainTicket, resp);
                    return resp;
                })
                .collect(Collectors.toList());

        PageResp<DailyTrainTicketQueryResp> pageResp = new PageResp<>();
        pageResp.setTotal(pageInfo.getTotal());
        pageResp.setList(list);
        return pageResp;
    }

    @Override
    public void delete(Long id) {
        dailyTrainTicketMapper.deleteByPrimaryKey(id);
    }

    @Transactional
    public void genDaily(DailyTrain dailyTrain,Date date, String trainCode) {
        log.info("生成日期【{}】余票【{}】的座位信息开始", DateUtil.formatDate(date), trainCode);

        //删除车次的余票
        DailyTrainTicketExample dailyTrainTicketExample = new DailyTrainTicketExample();
        dailyTrainTicketExample.createCriteria()
                .andDateEqualTo(date)
                .andTrainCodeEqualTo(trainCode);
        dailyTrainTicketMapper.deleteByExample(dailyTrainTicketExample);

        // 查出某车次的所有的车站信息
        List<TrainStation> stationList = trainStationService.selectByUniqueTrainCode(trainCode);

        if (CollUtil.isEmpty(stationList)) {
            log.info("该车次没有车站基础数据，生成该车次的余票信息结束");
            return;
        }

        DateTime now = DateTime.now();

        //查询同一时间下的同一车次下的不同座位类型的车票数量
        //单次列车的初始化的座位类型的数量不变  在循环外进行获取  减少时间复杂度
        int ydzCount =  dailyTrainSeatService.countSeat(trainCode,date, SeatTypeEnum.YDZ.getCode());
        int edzCount =  dailyTrainSeatService.countSeat(trainCode,date, SeatTypeEnum.EDZ.getCode());
        int rwCount =  dailyTrainSeatService.countSeat(trainCode,date, SeatTypeEnum.RW.getCode());
        int ywCount =  dailyTrainSeatService.countSeat(trainCode,date, SeatTypeEnum.YW.getCode());

        //火车类型
        String trainType = dailyTrain.getType();
        for (int i = 0; i < stationList.size(); i++) {
            //开实站 到 目的地的里程数
            BigDecimal sumKM  = BigDecimal.ZERO;
            TrainStation startTrainStation = stationList.get(i);
            for (int j = i+1; j < stationList.size(); j++){
                TrainStation endTrainStation = stationList.get(j);
                sumKM = sumKM.add(endTrainStation.getKm());
                //生成每日的余票
                DailyTrainTicket dailyTrainTicket = new DailyTrainTicket();
                dailyTrainTicket.setId(IdUtil.getSnowflake(1,1).nextId());
                dailyTrainTicket.setDate(date);
                dailyTrainTicket.setTrainCode(trainCode);
                dailyTrainTicket.setStart(startTrainStation.getName());
                dailyTrainTicket.setStartPinyin(startTrainStation.getNamePinyin());
                dailyTrainTicket.setStartTime(startTrainStation.getOutTime());
                dailyTrainTicket.setStartIndex(startTrainStation.getIndex());
                dailyTrainTicket.setEnd(endTrainStation.getName());
                dailyTrainTicket.setEndPinyin(endTrainStation.getNamePinyin());
                dailyTrainTicket.setEndTime(endTrainStation.getInTime());
                dailyTrainTicket.setEndIndex(endTrainStation.getIndex());
                dailyTrainTicket.setYdz(ydzCount);
                dailyTrainTicket.setEdz(edzCount);
                dailyTrainTicket.setRw(rwCount);
                dailyTrainTicket.setYw(ywCount);
                //票价 = 里程数 * 火车类型单价 * 座位类型单价
                //获取火车类型单价
                BigDecimal trainPriceRate = BigDecimal.ZERO;
                boolean flag = false;
                for (TrainTypeEnum type : TrainTypeEnum.values()) {
                    if (type.getCode().equals(trainType)) {
                        trainPriceRate = type.getPriceRate();
                        flag = true;
                    }
                }
                if(!flag){
                    throw new RuntimeException("火车类型不存在");
                }
                //计算座位价格
                BigDecimal ydzPrice = sumKM.multiply(SeatTypeEnum.YDZ.getPrice()).multiply(trainPriceRate).setScale(0, RoundingMode.HALF_UP);
                BigDecimal edzPrice = sumKM.multiply(SeatTypeEnum.EDZ.getPrice()).multiply(trainPriceRate).setScale(0, RoundingMode.HALF_UP);
                BigDecimal rwPrice = sumKM.multiply(SeatTypeEnum.RW.getPrice()).multiply(trainPriceRate).setScale(0, RoundingMode.HALF_UP);
                BigDecimal ywPrice = sumKM.multiply(SeatTypeEnum.YW.getPrice()).multiply(trainPriceRate).setScale(0, RoundingMode.HALF_UP);
                //封装数据
                dailyTrainTicket.setYdzPrice(ydzPrice);
                dailyTrainTicket.setEdzPrice(edzPrice);
                dailyTrainTicket.setRwPrice(rwPrice);
                dailyTrainTicket.setYwPrice(ywPrice);
                dailyTrainTicket.setCreateTime(now);
                dailyTrainTicket.setUpdateTime(now);
                dailyTrainTicketMapper.insert(dailyTrainTicket);
            }
        }
        log.info("生成日期【{}】车次【{}】的余票信息结束", DateUtil.formatDate(date), trainCode);
    }

    @Override
    public DailyTrainTicket selectByUnique(Date date, String trainCode, String start, String end) {
        DailyTrainTicketExample dailyTrainTicketExample = new DailyTrainTicketExample();
        dailyTrainTicketExample.createCriteria()
                .andDateEqualTo(date)
                .andTrainCodeEqualTo(trainCode)
                .andStartEqualTo(start)
                .andEndEqualTo(end);
        List<DailyTrainTicket> list = dailyTrainTicketMapper.selectByExample(dailyTrainTicketExample);
        if (CollUtil.isNotEmpty(list)) {
            return list.get(0);
        } else {
            return null;
        }
    }
}